package com.cupcorn.balapkarung.state;

import java.util.ArrayList;

import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.scene.ITouchArea;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.util.FPSLogger;
import org.andengine.extension.tmx.TMXTiledMap;
import org.andengine.input.touch.TouchEvent;
import org.andengine.input.touch.detector.ClickDetector;
import org.andengine.input.touch.detector.ScrollDetector;
import org.andengine.util.color.Color;

import android.view.KeyEvent;
import android.widget.Toast;

import com.cupcorn.balapkarung.GameDefine;
import com.cupcorn.balapkarung.GameDefineText;
import com.cupcorn.balapkarung.LocalData;
import com.cupcorn.balapkarung.entity.Camera;
import com.cupcorn.balapkarung.entity.MC;
import com.cupcorn.balapkarung.entity.Map;
import com.cupcorn.balapkarung.entity.World;
import com.cupcorn.lib.Utils;
import com.cupcorn.lib.define.iDefines;
import com.cupcorn.lib.display.DisplayAnimatedSprite;
import com.cupcorn.lib.display.DisplayAutoParallax;
import com.cupcorn.lib.display.DisplaySprite;
import com.cupcorn.lib.display.DisplayText;
import com.cupcorn.lib.display.DisplayTmx;
import com.cupcorn.lib.game.GameAutoParallax;
import com.cupcorn.lib.game.GameEngine;
import com.cupcorn.lib.game.GameSprite;
import com.cupcorn.lib.game.GameState;
import com.cupcorn.onlinescript.OnlineScript;

public class StateGamePlay extends GameState implements GameDefine, GameDefineText
{
	public static final int	MAX_MC_COUNT	= 4;
	
	// DisplaySprite displaySprite;
	DisplaySprite			displaySprite;
	DisplayAutoParallax		displayAutoParallax;
	DisplayAnimatedSprite	displayAnimatedSprite;
	DisplayTmx				displayTmx, displayTmx2;
	public DisplayText		displayText;
	
	TMXTiledMap				tiledMap;
	GameAutoParallax		parallax;
	GameSprite				background1;
	GameSprite				background2;
	GameSprite				icon;
	public static MC[]		mc;
	World					world;
	Map						map, map2;
	Camera					camera;
	StateGamePlayOnline		online;
	
	public float			xTextStart, yTextStart, xTextDistance, yTextDistance, timeMove = 1, widthText;
	
	public static int		score;
	public static boolean	isReset, isOnline, soundIngamePlayed;
	
	int						curMc, mcCount;
	
	public StateGamePlay(GameEngine engine)
	{
		super(engine);
	}
	
	public void load()
	{
		displayAutoParallax = new DisplayAutoParallax(engine, GAME_AUTO_PARALAX);
		displaySprite = new DisplaySprite(engine, GAME_PLAY_SPR);
		displayTmx = new DisplayTmx(engine, GAME_PLAY_TMX);
		displayTmx2 = new DisplayTmx(engine, GAME_PLAY_TMX);
		displayAnimatedSprite = new DisplayAnimatedSprite(engine, GAME_PLAY_MC);
		displayText = new DisplayText(engine, engine.displayFont, TEXT);
	}
	
	@SuppressWarnings("deprecation")
	public void init()
	{
		if (!true)
		{
			final FPSLogger m_Fps = new FPSLogger();
			engine.getEngine().registerUpdateHandler(m_Fps);
			displayText.newText(TEXT_TRACE, engine.hud);
			
			engine.getEngine().registerUpdateHandler(new TimerHandler(0.5f, true, new ITimerCallback()
			{
				@Override
				public void onTimePassed(final TimerHandler pTimerHandler)
				{
					displayText.text[TEXT_TRACE].setText("FPS: " + m_Fps.getFPS());
				}
			}));
		}
		
		isOnline = !false;
		
		displayTmx.newTiledMap(0);
		displayTmx2.newTiledMap(0);
		
		background1 = displaySprite.sprite(1);
		background2 = displaySprite.sprite(1);
		background2.setX(GameEngine.CAMERA_WIDTH);
		
		parallax = displayAutoParallax.newSprite(0);
		
		parallax.addEntity(-5, background1);
		parallax.addEntity(-5, background2);
		
		icon = displaySprite.sprite(0);
		icon.setVisible(false);
		
		mc = new MC[MAX_MC_COUNT];
		mc[0] = new MC(engine, displayAnimatedSprite.newAnimatedSprite(LocalData.character_use), Utils.getUsername(), icon);
		
		map = new Map(engine, displayTmx, mc[0], 0);
		map2 = new Map(engine, displayTmx2, null, (int) map.recMap.getWidth());
		world = new World(engine, this, parallax, mc, map, map2);
		camera = new Camera(engine.camera, mc[0], map, map2);
		
		online = new StateGamePlayOnline(engine, this);
		
		isReset = false;
		
		displayText.newText(TEXT_SCORE, engine.hud).setVisible(false);
		displayText.newText(TEXT_SCORE_MOVE, engine.hud);
		
		displayText.text[TEXT_SCORE].setColor(Color.BLACK);
		displayText.text[TEXT_SCORE_MOVE].setColor(Color.BLACK);
		
		widthText = displayText.text[TEXT_SCORE].getWidth();
		
		xTextStart = displayText.text[TEXT_SCORE_MOVE].getX();
		yTextStart = displayText.text[TEXT_SCORE_MOVE].getY();
		
		xTextDistance = displayText.text[TEXT_SCORE_MOVE].getX() - displayText.text[TEXT_SCORE].getX() - widthText;
		yTextDistance = displayText.text[TEXT_SCORE_MOVE].getY() - displayText.text[TEXT_SCORE].getY();
		
		try
		{
			engine.ToastMakeText(1, OnlineScript.returnArray.toString(), Toast.LENGTH_LONG);
		}
		catch (Exception e)
		{
			engine.ToastMakeText(1, e.getMessage(), Toast.LENGTH_LONG);
		}
		
		soundIngamePlayed = false;
	}
	
	public void update(float deltaTime)
	{
		if (isReset) reset();
		
		mc[0].onUpdate(deltaTime);
		
		if (isOnline)
		{
			online.update(deltaTime);
		}
		else
		{
			if (LocalData.listReplayJump.size() > 0)
			{
				mc[1].replay(LocalData.listReplayJump.size() - 1);
				mc[1].onUpdate(deltaTime);
			}
		}

		world.onUpdate(deltaTime);
		camera.onUpdate();
		
		score(deltaTime);
		nameActive(deltaTime);
		
		if (readyToGameOver())
		{
			engine.nextState(GameDefine.STATE_GAME_OVER, iDefines.MESSAGE_STATE_INIT);
		}
	}
	
	public void exit()
	{
		mc[0].reset();
		camera.reset();
		
		icon.setVisible(false);
		displayText.text[TEXT_SCORE].setVisible(false);
		
		for (int i = 1; i < MAX_MC_COUNT; i++)
		{
			mc[i].linkedText.setAlpha(0);
			mc[i].displayText.text[0].setAlpha(0);
			mc[i].mc.setVisible(false);
		}
	}
	
	public boolean keyUp(int keyCode, KeyEvent event)
	{
		if (keyCode == KeyEvent.KEYCODE_BACK)
		{
			// engine.finish();
		}
		return false;
	}
	
	public void sceneTouch(Scene scene, TouchEvent touchEvent)
	{
		if (mc[0].curState != mc[0].DIE)
		{
			if (touchEvent.isActionDown() && mc[0].curJump < mc[0].MAX_JUMP)
			{
				mc[0].switchState(mc[0].JUMP);
				
				LocalData.listJump.add((int) mc[0].mc.getX());
			}
			
			if (touchEvent.isActionUp())
			{
				mc[0].switchState(mc[0].DOWN);
				
				LocalData.listJump.add((int) mc[0].mc.getX());
			}
		}
	}
	
	public boolean onAreaTouched(TouchEvent pSceneTouchEvent, ITouchArea pTouchArea, float pTouchAreaLocalX, float pTouchAreaLocalY)
	{
		return false;
	}
	
	public void click(ClickDetector clickDetector, int pointerID, float sceneX, float sceneY)
	{	
		
	}
	
	public void scrollStarted(ScrollDetector scrollDetector, int pointerID, float distanceX, float distanceY)
	{	
		
	}
	
	public void Scroll(ScrollDetector scrollDetector, int pointerID, float distanceX, float distanceY)
	{	
		
	}
	
	public void scrollFinished(ScrollDetector scrollDetector, int pointerID, float distanceX, float distanceY)
	{	
		
	}
	
	private void reset()
	{
		LocalData.listJump = new ArrayList<Integer>();
		
		exit();
		
		if (isOnline)
		{
			online.reset();
			mcCount = 4;
		}
		else
		{
			if (LocalData.listReplayJump.size() > 0)
			{
				mcCount = 2;
				
				mc[1].setName("Your Best Run");
				mc[1].reset();
				mc[1].switchState(mc[0].MOVE);
				mc[1].curJump = mc[0].MAX_JUMP;
				mc[1].curGravitation = 600;
				online.resetPosition(1);
			}
			else
			{
				mcCount = 1;
			}
		}
		
		mc[0].switchState(mc[0].MOVE);
		parallax.setParallaxChangePerSecond(5);
		
		icon.setVisible(true);
		displayText.text[TEXT_SCORE].setVisible(true);
		
		curMc = 0;
		for (int i = 0; i < MAX_MC_COUNT; i++)
		{
			mc[i].curTime = 0;
		}
		
		if (!soundIngamePlayed)
		{
			engine.playerMusic.play(MUSIC_INGAME);
			soundIngamePlayed = true;
		}
		
		isReset = false;
	}
	
	private void score(float deltaTime)
	{
		if (mc[0].curState != mc[0].DIE)
		{
			score = (int) ((mc[0].mc.getX() - mc[0].xStart) / 10);
			displayText.text[TEXT_SCORE].setText("Score : " + score);
			
			if (score % 500 == 0 && score != 0)
			{
				displayText.text[TEXT_SCORE_MOVE].setText("" + score);
				displayText.text[TEXT_SCORE_MOVE].setScale(2);
			}
			
			if (displayText.text[TEXT_SCORE_MOVE].getText().length() != 0)
			{
				displayText.text[TEXT_SCORE_MOVE].setScale(displayText.text[TEXT_SCORE_MOVE].getScaleX() - 1 / timeMove * deltaTime);
				displayText.text[TEXT_SCORE_MOVE].setPosition(displayText.text[TEXT_SCORE_MOVE].getX() - xTextDistance / timeMove * deltaTime,
					displayText.text[TEXT_SCORE_MOVE].getY() - yTextDistance / timeMove * deltaTime);
				
				if (displayText.text[TEXT_SCORE_MOVE].getY() < displayText.text[TEXT_SCORE].getY())
				{
					displayText.text[TEXT_SCORE_MOVE].setText("");
					displayText.text[TEXT_SCORE_MOVE].setPosition(xTextStart, yTextStart);
				}
			}
		}
	}
	
	private boolean readyToGameOver()
	{
		boolean gotoGameover = false;
		
		if (mc[0].curState == mc[0].DIE)
		{
			gotoGameover = true;
			
			if (mc[0].mc.getY() - icon.getHeight() < engine.getEngine().getCamera().getYMax())
			{
				gotoGameover = false;
			}
			
			for (int i = 0; i < mcCount; i++)
			{
				if (i > 0)
					if (mc[i].mc.getX() < engine.getEngine().getCamera().getXMax() &&
						mc[i].mc.getX() + mc[i].mc.getWidth() > engine.getEngine().getCamera().getXMin() &&
						mc[i].mc.getY() < engine.getEngine().getCamera().getYMax())
					{
						gotoGameover = false;
					}
			}
		}
		
		return gotoGameover;
	}
	
	private void nameActive(float deltaTime)
	{
		mc[curMc].setTextAndLinked(deltaTime);
		if (mc[curMc].curTime > mc[curMc].timeAlpha * 2 + mc[curMc].timeVisible)
		{
			curMc++;
			if (curMc == mcCount) curMc = 0;
			while (mc[curMc].curState == mc[curMc].DIE && curMc != 0)
			{
				curMc++;
				if (curMc == mcCount) curMc = 0;
			}
			
			mc[curMc].curTime = 0;
		}
	}
}
